using System;
using System.Collections.Generic;
using System.Linq;
using Kiwi.Container.Activation;
using Kiwi.Container.DependencyInjection;

namespace Kiwi.Container
{
    public static class ComponentResolverExtensions
    {
        public static object TryResolve(this IComponentResolver resolver, Type type)
        {
            return resolver.TryResolve(type, null);
        }

        public static object Resolve(this IComponentResolver resolver, Type type)
        {
            return resolver.Resolve(type, null);
        }

        public static T TryResolve<T>(this IComponentResolver resolver)
        {
            return (T) resolver.TryResolve(typeof (T), null);
        }

        public static T TryResolve<T>(this IComponentResolver resolver, Func<IComponentRegistration, bool> filter)
        {
            return (T) resolver.TryResolve(typeof (T), filter);
        }

        public static T TryResolve<T>(this IComponentResolver resolver, object tag)
        {
            return (T) resolver.TryResolve(typeof (T), c => Equals(c.Tag, tag));
        }

        public static T Resolve<T>(this IComponentResolver resolver)
        {
            return (T) resolver.Resolve(typeof (T), null);
        }

        public static T Resolve<T>(this IComponentResolver resolver, Func<IComponentRegistration, bool> filter)
        {
            return (T) resolver.Resolve(typeof (T), filter);
        }

        public static T Resolve<T>(this IComponentResolver resolver, object tag)
        {
            return (T) resolver.Resolve(typeof (T), c => Equals(c.Tag, tag));
        }

        public static IEnumerable<T> ResolveAll<T>(this IComponentResolver resolver)
        {
            return resolver.ResolveAll(typeof (T), null).Cast<T>();
        }

        public static IEnumerable<T> ResolveAll<T>(this IComponentResolver resolver,
                                                   Func<IComponentRegistration, bool> filter)
        {
            return resolver.ResolveAll(typeof (T), filter).Cast<T>();
        }

        public static IEnumerable<T> ResolveAll<T>(this IComponentResolver resolver, object tag)
        {
            return resolver.ResolveAll(typeof (T), c => Equals(c.Tag, tag)).Cast<T>();
        }

        public static T Construct<T>(this IComponentResolver resolver)
        {
            return resolver.Construct<T>(Properties.None);
        }

        public static T Construct<T>(this IComponentResolver resolver, IEnumerateDependentProperties dependentProperties)
        {
            var instance = new BestFitConstructorComponentActivator<T>().ActivateComponent(resolver);
            resolver.Inject(instance, dependentProperties);
            return (T) instance;
        }
    }
}